package com.brayan.webapp.model.usermgmt;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

import com.brayan.webapp.model.general.Modification;

/**
 * This User type can be used for registered, visiting users, tenants or others.
 * 
 * @author Brayan
 * 
 */
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class User implements Serializable {
	/** Default value included to remove warning. Remove or modify at will. **/
	private static final long serialVersionUID = 1L;

	/***** ATTRIBUTES *****/
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	// TODO Must set initial value of user number to 100000 or 50000
	// @SequenceGenerator(name = "UserSeqGen", initialValue = 10000)
	private Long id;

	@ManyToMany(cascade={CascadeType.DETACH, CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST})
	private Set<Role> roles = new HashSet<Role>();
	
	@OneToMany(cascade=CascadeType.ALL)
	private List<Modification> modifications = new ArrayList<Modification>();

	@Size(min = 2, max = 100)
	private String username;
	private String surname;
	private String givenname;
	private Sex sex;

	private String password;
	@Column(unique = true)
	@Email
	private String email;

	@Size(min = 9, max = 15)
	// @Digits(fraction = 0, integer = 15)
	// @Column(name = "phone")
	private String phone;
	private String mobile;

	/** Cryptic key to remember a user on the graphical user interface. */
	private String rememberMeKey;

	@SuppressWarnings("unused")
	private Date dateCreated;
	@SuppressWarnings("unused")
	private Date dateModified;

	/***** EVENT HOOKS *****/

	@PrePersist
	protected void onCreate() {
		dateCreated = new Date();
	}

	@PreUpdate
	protected void onUpdate() {
		dateModified = new Date();
	}

	/***** GETTER AND SETTERS *****/

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}
	
	/**
	 * Add a role providing the role type.
	 * @param roleType
	 */
	public void addRole(Role role){		
		this.roles.add(role);
	}

	/**
	 * This function returns the email address if no user name is set.
	 * Use {@link #getTrueUsername()} for the real user name.
	 * @return
	 */
	public String getUsername() {
		if(!username.isEmpty())
			return username;
		else
			return email;
	}
	
	public String getTrueUsername(){
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getGivenname() {
		return givenname;
	}

	public void setGivenname(String givenname) {
		this.givenname = givenname;
	}

	public Sex getSex() {
		return sex;
	}

	public void setSex(Sex sex) {
		this.sex = sex;
	}

	public String getSurname() {
		return surname;
	}

	public void setSurname(String surname) {
		this.surname = surname;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	public String getRememberMeKey() {
		return rememberMeKey;
	}

	public void setRememberMeKey(String rememberMeKey) {
		this.rememberMeKey = rememberMeKey;
	}
	
	public List<Modification> getModifications() {
		return modifications;
	}
	public void setModifications(List<Modification> modifications) {
		this.modifications = modifications;
	}
	
	public void addModification(Modification modification){
		this.modifications.add(modification);
	}

}